import ChartBase from "./chart-base";
import { deepClone, mergeObject } from "@/utils";
import { handleTree } from "@/utils/ruoyi";

const Number = ["一", "二", "三", "四", "五", "六"];

export default class Sankey extends ChartBase {
  constructor() {
    super();
  }

  // 基础描述
  _info = {
    name: "桑基图",
    type: "sankey", // 图表类型
    group: "sankey", // 图表分类
    component: "e-chart",
    icon: "sankey", // 图表展示ICON
  };

  // 总 配置项
  _defaultOption = {
    tooltip: {
      trigger: "item",
      triggerOn: "mousemove",
      formatter: (item) => {
        return item.data.name ? item.name : "";
      },
      extraCssText: "max-width:500px; white-space:pre-wrap",
    },
    title: [
      // {
      //   text: "物质输入",
      //   padding: 20,
      //   itemGap: 10,
      //   textStyle: {
      //     fontSize: 18,
      //   },
      //   top: "top",
      //   left: "5%",
      // },
      // {
      //   text: "行业",
      //   padding: 20,
      //   itemGap: 10,
      //   textStyle: {
      //     fontSize: 18,
      //   },
      //   top: "top",
      //   left: "40%",
      // },
      // {
      //   text: "物质输出",
      //   padding: 20,
      //   itemGap: 10,
      //   textStyle: {
      //     fontSize: 18,
      //   },
      //   top: "top",
      //   left: "75%",
      // },
    ],
    series: [],
  };

  // 系列
  _defaultSeries = {
    type: "sankey",
    layout: "none",
    top: 50,
    left: 40,
    // nodeWidth: 40,
    // right: 10,
    layoutIterations: 0, // 自动优化列表，尽量减少线的交叉，为0就是按照数据排列

    draggable: false,
    label: {
      formatter: (item) => {
        return item.data.name.length > 10
          ? item.data.name.slice(0, 10) + "..."
          : item.data.name;
      },
    },
    emphasis: {
      focus: "adjacency",
    },

    data: [],
    links: [], // 节点之间的连线
  };

  // 数据结构描述
  _dataPoolConfig = [
    {
      label: "节点名称",
      key: "nameField",
      type: ["string"],
      limit: 1,
      description: "关系图节点的名称字段, 字段类型为「 字符类型 」",
      width: "50%",
    },
    {
      label: "描述名称",
      key: "describe",
      type: ["string"],
      limit: 1,
      description: "关系图节点的名称描述字段, 字段类型为「 字符类型 」",
      width: "50%",
    },
    {
      label: "主键字段",
      key: "idField",
      type: ["string", "date", "number"],
      limit: 1,
      description: "字段类型为「 数字类型 」或 「 字符类型 」",
      width: "50%",
    },
    {
      label: "关系字段",
      key: "relationField",
      type: ["string", "date", "number"],
      limit: 1,
      description:
        "用于展示节点之间的关系, 字段类型为「 数字类型 」或 「 字符类型 」",
      width: "50%",
    },
  ];

  //样式配置描述信息
  _styleOptionConfig = [
    {
      label: "标题配置",
      bindKeys: "_group.echart",
      controlType: "group",
      controlValue: "",
      controlProps: {},
      controlConfigs: {},
    },
    {
      label: "显示",
      bindKeys: "config.title.show",
      controlType: "switch",
      controlValue: true,
      controlProps: {},
      controlConfigs: {},
    },
  ];

  getOption({
    dataList = [],
    dataTotal = 0,
    dataPoolField,
    styleOptionConfig = [],
    themeColor = [],
    themeStyle = {},
  }) {
    let { option, series, config } =
      this._transformStyleOptionConfig(styleOptionConfig);
    let defaultOption = deepClone(this._defaultOption);
    let defaultSeries = deepClone(this._defaultSeries);

    if (defaultOption && option)
      defaultOption = mergeObject(defaultOption, option);
    if (defaultSeries && series)
      defaultSeries = mergeObject(defaultSeries, series);

    defaultOption.color = themeColor;

    const checkHasValue = (array) =>
      array && array instanceof Array && array.length > 0;

    let treeData;

    // 处理连线数据
    if (
      checkHasValue(dataPoolField["idField"]) &&
      checkHasValue(dataPoolField["relationField"])
    ) {
      treeData = handleTree(
        dataList,
        dataPoolField["idField"][0].fieldName,
        dataPoolField["relationField"][0].fieldName
      );

      //----------------------------------------
    }

    // 处理节点数据
    if (
      checkHasValue(dataPoolField["idField"]) &&
      checkHasValue(dataPoolField["nameField"]) &&
      checkHasValue(dataPoolField["describe"]) &&
      checkHasValue(dataPoolField["relationField"])
    ) {
      const idField = dataPoolField["idField"][0].fieldName;
      const nameField = dataPoolField["nameField"][0].fieldName;
      const describe = dataPoolField["describe"][0].fieldName;

      this.changeData(treeData, 0);

      let field = [nameField, describe, idField];

      let { nodesData, linesData, titleData } = this.setLinesData(
        treeData,
        field
      );

      if (titleData.length) {
        titleData.forEach((item, index) => {
          item.left = `${
            index * (100 / titleData.length - 1) + 5 * (index + 1)
          }%`;
        });
      }

      defaultSeries.links = linesData;

      defaultSeries.data = nodesData;

      defaultOption.title = config.title.show ? titleData : [];
    }

    defaultOption.series.push({
      ...defaultSeries,
    });

    return defaultOption;
  }

  changeData(treeData, level) {
    let nums = 0;
    treeData.forEach((item) => {
      item.level = level + 1;

      if (item.children && item.children.length) {
        this.changeData(item.children, level + 1);
      }
      item.number = item.children?.length || 1; // 子节点数量
      // 计算当前节点所有子元素集合的最大长度
      item.total = item.children
        ? item.children.reduce((r, c) => {
            r += c.total ? c.total : c.number;
            return r;
          }, 0)
        : 0;

      nums += item.total > item.number ? item.total : item.number;
    });
  }

  setLinesData(treeData, field, lines, nodes, title) {
    let info = {
      linesData: lines || [],
      nodesData: nodes || [],
      titleData: title || [],
    };
    treeData.forEach((item, index) => {
      let obj = {
        id: item[field[2]],
        name: item[field[0]] + (item[field[1]] ? `(${item[field[1]]})` : ""),
        depth: item.level - 1,
      };

      if (item.level === 1 && (!item.children || !item.children.length)) {
        obj.value = 1;
      }
      info.nodesData.push(obj);
      if (
        !info.titleData.find(
          (f) => f.text === `${Number[item.level - 1]}级数据分类`
        )
      ) {
        info.titleData.push({
          text: `${Number[item.level - 1]}级数据分类`,

          textStyle: {
            fontSize: 18,
          },
          top: "top",
        });
      }

      if (item.children && item.children.length) {
        item.children.forEach((child) => {
          info.linesData.push({
            source: `${item[field[2]]}`,
            target: `${child[field[2]]}`,
            value: child.total ? child.total : child.number,
          });
        });
        info = this.setLinesData(
          item.children,
          field,
          info.linesData,
          info.nodesData,
          info.titleData
        );
      }
    });

    return info;
  }

  getClickData(event) {
    const { name, seriesName, value } = event;

    return {
      label: name,
      value: value[seriesName],
    };
  }
}
